package spring.reflect;

import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * <p>类描述：反射。</p>
 *
 * @author 贾亮
 * @version v1.0.0.1。
 * @since JDK1.8。
 * <p>创建日期：2018/3/8 16:49。</p>
 */
public class Main {

    /**
     * 获取Person类的类型
     */
    @Test
    public void ClassType() {
        try {
            Person person = new Person();
            System.out.println(Person.class);
            System.out.println(person.getClass());
            System.out.println(Class.forName("spring.reflect.Person"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取Person类的特定方法fun并执行
     */
    @Test
    public void Method() {
        try {
            Person person = new Person();
            String className = Person.class.toString();
            className = className.replace("class ", "");
            // 先生成class
            Class c = Class.forName(className);
            // 初始化一个实例
            Object o = c.newInstance();
            // 获取指定方法
            Method method = c.getMethod("fun", String.class, int.class);
            // 通过invoke调用该方法，参数第一个为实例对象，后面为具体参数值
            System.out.println("Person类fun方法的执行结果：");
            method.invoke(o, "小明" , 20);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取类的所有声明方法，不包括父类的
     */
    @Test
    public void AllMethods() {
        Class c = Person.class;
        Method[] methods1 = c.getDeclaredMethods();
        System.out.println("Person类的所有声明方法为：");
        for (Method m : methods1) {
            System.out.println(m);
        }
    }

    /**
     * 获取类的所有public方法，包括父类的
     */
    @Test
    public void AllPublicMethods() {
        Class c = Person.class;
        Method[] methods2 = c.getMethods();
        System.out.println("Person类以及父类的所有public方法为：");
        for (Method m : methods2) {
            System.out.println(m);
        }
    }

    /**
     * 获取该类指定成员变量的值
     */
    @Test
    public void Variable() {
        try {
            Class c = Person.class;
            // 获取该类所有成员变量(不包括父类)中指定的成员变量，
            Field field = c.getDeclaredField("msg");
            // 初始化一个实例
            Object o = c.newInstance();
            // 设置是否允许访问，因为该变量是private的，所以要手动设置允许访问，如果msg是public的就不需要这行了。
            field.setAccessible(true);
            // 获取该变量的值
            Object msg = field.get(o);
            System.out.println(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取所有变量名
     */
    @Test
    public void VribleNames() {
        Class c = Person.class;
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
    }

}
